home *** CD-ROM | disk | FTP | other *** search
/ Delphi 2 - Developers' Solutions / Delphi 2 Developers' Solutions.iso / dds / comps / widgets / delphi10 / thuicpnl / thuicpnl.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1996-06-17  |  22.5 KB  |  656 lines

  1. unit Thuicpnl;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  7.   Forms, Dialogs, ExtCtrls, FILICPNL, ResUnit;
  8.  
  9. type
  10.   TThumbNailFileIconPanel = class(TFileIconPanel)
  11.   public
  12.     FTheBMP : TBitmap;
  13.     { Public declarations }
  14.     procedure Paint; override;                { This allows custom painting  }
  15.     procedure Initialize( PanelX              ,
  16.                           PanelY              ,
  17.                           PanelWidth          ,
  18.                           PanelHeight         ,
  19.                           PanelBevelWidth     ,
  20.                           LabelFontSize         : Integer;
  21.                           PanelColor          ,
  22.                           PanelHighlightColor ,
  23.                           PanelShadowColor    ,
  24.                           LabelTextColor        : TColor;
  25.                           TheFilename         ,
  26.                           LabelFontName         : String;
  27.                           LabelFontStyle        : TFontStyles;
  28.                           ExtraData             : Integer ); override;
  29.   end;
  30.  
  31. function CreateBitmapThumbNailFromBitmap( SourceBMP: TBitmap;
  32.                                           TargetWidth ,
  33.                                           TargetHeight : Integer ) : TBitmap;
  34. procedure Register;
  35.  
  36. implementation
  37.  
  38. type
  39.   File_BitMap = class( TObject )
  40.   public
  41.     Bitmap_Handle    : HBitmap;   { Holds the DIB when done               }
  42.     Width            : Longint;   { Holds the pixel width when done       }
  43.     Height           : Longint;   { Holds the pixel height when done      }
  44.     The_File         : File;      { File variable for internal use        }
  45.     The_Name         : String;    { Holds the file name                   }
  46.     Bits_Handle      : THandle;   { temporary holder for the DIB          }
  47.     Bits_Byte_Size   : Longint;   { temporary holder for the              }
  48.                                   { byte length of the DIB                }
  49.     Error_Status     : Integer;   { code for error condition on the DIB   }
  50.  
  51.     constructor Create;
  52.     procedure Initialize( The_DIB_Name : String );
  53.     destructor Destroy;
  54.     procedure Get_Bitmap_Data;
  55.     function Get_Bitmap : HBitmap;
  56.     function Load_Bitmap_File : Boolean;
  57.     function Open_DIB : Boolean;
  58.     function Get_Error_Status : Integer;
  59.     procedure Get_DIB_Dimensions( var The_Width  ,
  60.                                       The_Height   : Longint );
  61.   end;
  62.  
  63. procedure AHIncr; FAR; EXTERNAL 'KERNEL' INDEX 114;
  64.  
  65. var
  66.   ThumbNailWidth : integer;
  67.   ThumbNailHeight : integer;
  68.  
  69. function CreateBitmapThumbNailFromBitmap( SourceBMP: TBitmap;
  70.                                           TargetWidth ,
  71.                                           TargetHeight : Integer ) : TBitmap;
  72. var OutputBMP : TBitmap;
  73.     HoldingBMP : TBitmap;
  74.     TotalSourceColsPerOutputCol,
  75.     TotalSourceRowsPerOutputRow,
  76.     Counter_1 ,
  77.     Counter_2 ,
  78.     Counter_3 : Integer;
  79.     CurrentColor : Longint;
  80.     CurrentRowPointer,
  81.     CurrentColPointer,
  82.     BestLineSoFar ,
  83.     TotalColorsInWork : Integer;
  84.     MaxColorsSoFar    : Integer;
  85. begin
  86.   { if source smaller than or equal to thumbnail, stretchdraw and leave }
  87.   if (( SourceBMP.Width <= TargetWidth ) and
  88.       ( SourceBMP.Height <= TargetHeight )) then
  89.   begin
  90.     OutputBMP := TBitmap.Create;
  91.     OutputBMP.Height := TargetHeight;
  92.     OutputBMP.Width := TargetWidth;
  93.     OutputBMP.Canvas.StretchDraw( Rect( 0 , 0 , TargetWidth , TargetHeight ) ,
  94.      SourceBMP );
  95.     CreateBitmapThumbNailFromBitmap := OutputBMP;
  96.     exit;
  97.   end;
  98.   { Otherwise do thumbnail algorithm }
  99.   { Create the interim holding bitmap; it will hold full width but resized # rows }
  100.   HoldingBMP := TBitmap.Create;
  101.   HoldingBMP.Width := SourceBMP.Width;
  102.   HoldingBMP.Height := TargetHeight;
  103.   { Create the final output bitmap; it will hold the resized values in both h & w }
  104.   OutputBMP := TBitmap.Create;
  105.   OutputBMP.Width := TargetWidth;
  106.   OutputBMP.Height := TargetHeight;
  107.   { Determine the total source rows and cols per output row and col }
  108.   TotalSourceRowsPerOutputRow := ( SourceBMP.Height div TargetHeight );
  109.   {if ( SourceBMP.Height mod TargetHeight ) <> 0 then
  110.    Inc( TotalSourceRowsPerOutputRow );}
  111.   TotalSourceColsPerOutputCol := ( SourceBMP.Width div TargetWidth );
  112.   {if ( SourceBMP.Width mod TargetWidth ) <> 0 then
  113.    Inc( TotalSourceColsPerOutputCol );}
  114.   { Start resizing by setting initial row pointer }
  115.   CurrentRowPointer := 0;
  116.   { Loop through desired number of output rows                       }
  117.   { Result will add row per group with highest color density to dest }
  118.   for Counter_1 := 1 to TargetHeight do
  119.   begin
  120.     { Reset colors per line, best cols per line, and best line pointers }
  121.     { Check all the lines in a group against each other }
  122.     TotalColorsInWork := 0;
  123.     MaxColorsSoFar := 0;
  124.     BestLineSoFar := 0;
  125.     for Counter_2 := 1 to TotalSourceRowsPerOutputRow do
  126.     begin
  127.       { Keep moving down the image }
  128.       Inc( CurrentRowPointer );
  129.       if CurrentRowPointer > SourceBMP.Height then break;
  130.       { Start with no color }
  131.       CurrentColor := -1;
  132.       TotalColorsInWork := 0;
  133.       { Actually scan the pixels }
  134.       for Counter_3 := 1 to SourceBMP.Width do
  135.       begin
  136.         { if the current pixel value is different than the stored one }
  137.         If SourceBMP.Canvas.Pixels[ Counter_3 - 1 , CurrentRowPointer - 1 ] <>
  138.          CurrentColor then
  139.         begin
  140.           { Make the new color the stored one }
  141.           CurrentColor := SourceBMP.Canvas.Pixels[ Counter_3 - 1 ,
  142.            CurrentRowPointer - 1 ];
  143.           { Increment total colors in the line }
  144.           Inc( TotalColorsInWork );
  145.         end;
  146.       end;
  147.       { At the end of the line, if there are more colors in the }
  148.       { current line than the previous best line, then }
  149.       if TotalColorsInWork > MaxColorsSoFar then
  150.       begin
  151.         { Set the new max to the current value }
  152.         MaxColorsSoFar := TotalColorsInWork;
  153.         { Set the new best line to the current pointer }
  154.         BestLineSoFar := CurrentRowPointer;
  155.       end;
  156.       { Reset the total colors being checked }
  157.       TotalColorsInWork := 0;
  158.     end;
  159.     MaxColorsSoFar := 0;
  160.     { Once best line is determined, copy all its pixels to the holding bmp }
  161.     for Counter_3 := 1 to SourceBMP.Width do
  162.     begin
  163.       HoldingBMP.Canvas.Pixels[ Counter_3 - 1 , Counter_1 - 1 ] :=
  164.        SourceBMP.Canvas.Pixels[ Counter_3 - 1 , BestLineSoFar - 1 ];
  165.     end;
  166.   end;
  167.   { Then resize by setting initial col pointer }
  168.   CurrentColPointer := 0;
  169.   { Loop through desired number of output cols                       }
  170.   { Result will add col per group with highest color density to dest }
  171.   for Counter_1 := 1 to TargetWidth do
  172.   begin
  173.     { Reset colors per line, best cols per line, and best line pointers }
  174.     TotalColorsInWork := 0;
  175.     MaxColorsSoFar := 0;
  176.     BestLineSoFar := 0;
  177.     { Check all the lines in a group against each other }
  178.     for Counter_2 := 1 to TotalSourceColsPerOutputCol do
  179.     begin
  180.       { Keep moving down the image }
  181.       Inc( CurrentColPointer );
  182.       if CurrentColPointer > HoldingBMP.Width then break;
  183.       { Start with no color }
  184.       CurrentColor := -1;
  185.       { Actually scan the pixels }
  186.       for Counter_3 := 1 to HoldingBMP.Height do
  187.       begin
  188.         { if the current pixel value is different than the stored one }
  189.         If HoldingBMP.Canvas.Pixels[ CurrentColPointer - 1 , Counter_3 - 1 ] <>
  190.          CurrentColor then
  191.         begin
  192.           { Make the new color the stored one }
  193.           CurrentColor := HoldingBMP.Canvas.Pixels[ CurrentColPointer - 1 ,
  194.            Counter_3 - 1 ];
  195.           { Increment total colors in the line }
  196.           Inc( TotalColorsInWork );
  197.         end;
  198.       end;
  199.       { At the end of the line, if there are more colors in the }
  200.       { current line than the previous best line, then }
  201.       if TotalColorsInWork > MaxColorsSoFar then
  202.       begin
  203.         { Set the new max to the current value }
  204.         MaxColorsSoFar := TotalColorsInWork;
  205.         { Set the new best line to the current pointer }
  206.         BestLineSoFar := CurrentColPointer;
  207.       end;
  208.       { Reset the total colors being checked }
  209.       TotalColorsInWork := 0;
  210.     end;
  211.     { Once best line is determined, copy all its pixels to the holding bmp }
  212.     for Counter_3 := 1 to HoldingBMP.Height do
  213.     begin
  214.       OutputBMP.Canvas.Pixels[ Counter_1 - 1 , Counter_3 - 1 ] :=
  215.        HoldingBMP.Canvas.Pixels[ BestLineSoFar - 1 , Counter_3 - 1 ];
  216.     end;
  217.   end;
  218.   { Finally, output the thumbnail image }
  219.   CreateBitmapThumbNailFromBitmap := OutputBMP;
  220.   { And free the working copy }
  221.   HoldingBMP.Free;
  222. end;
  223.  
  224. { This creates a file bitmap object }
  225. constructor File_BitMap.Create;
  226. begin
  227.   { call inherited FIRST! }
  228.   inherited Create;
  229.   { Zero out the data elements }
  230.   Bitmap_Handle := 0;
  231.   The_Name := '';
  232. end;
  233.  
  234. { This procedure sets up the bitmap filename to load }
  235. procedure File_BitMap.Initialize( The_DIB_Name : String );
  236. begin
  237.   The_Name := The_DIB_Name;
  238. end;
  239.  
  240. { This is the destructor procedure }
  241. destructor File_BitMap.Destroy;
  242. begin
  243.   { Assume bitmap handle given to TBitmap and cleared there }
  244.   { call inherited last }
  245.   inherited destroy;
  246. end;
  247.  
  248. { This method copies the bitmap bits data from the file into memory. Since }
  249. { copying cannot cross a segment (64K) boundary, segment arithmetic must   }
  250. { be done on the fly.  A LongType type was created to simplify this process}
  251. procedure File_BitMap.Get_Bitmap_Data;
  252.  
  253. type
  254.   LongType = record
  255.   case Word of
  256.     0: ( Ptr  : Pointer );
  257.     1: ( Long : Longint );
  258.     2: ( Lo   : Word;
  259.          Hi   : Word    );
  260.   end;
  261. var
  262.   Count   : Longint;
  263.   Start,
  264.   ToAddr,
  265.   Bits    : LongType;
  266. begin
  267.   Start.Long := 0;
  268.   Bits.Ptr := GlobalLock( Bits_Handle );
  269.   Count := Bits_Byte_Size - Start.Long;
  270.   while Count > 0 do
  271.   begin
  272.     ToAddr.Hi := Bits.Hi + ( Start.Hi * OFS( AHIncr ));
  273.     ToAddr.Lo := Start.Lo;
  274.     if Count > $4000 then Count := $4000;
  275.     BlockRead( The_File , ToAddr.Ptr^ , Count );
  276.     Start.Long := Start.Long + Count;
  277.     Count := Bits_Byte_Size - Start.Long;
  278.   end;
  279.   GlobalUnlock( Bits_Handle );
  280. end;
  281.  
  282. { This returns the handle to the stored bitmap }
  283. function File_BitMap.Get_Bitmap : HBitmap;
  284. begin
  285.   Get_Bitmap := Bitmap_Handle;
  286. end;
  287.  
  288. { This is the function to call to load a bitmap file of any size }
  289. { If no errors occur it returns true, otherwise false; use GEC   }
  290. { (Some portions of this code are copyright Borland Intl, 1990.) }
  291. function File_BitMap.Load_Bitmap_File : Boolean;
  292. var
  293.   Test_Win30_Bitmap : Longint;
  294.   Memory_DC         : HDC;
  295.   The_IO_Result     : Word;
  296. begin
  297.   Error_Status := 0;
  298.   Load_Bitmap_File := false;
  299.   AssignFile( The_File , The_Name );
  300.   {$I-}
  301.   Reset( The_File , 1 );
  302.   Seek( The_File , 14 );
  303.   BlockRead( The_File , Test_Win30_Bitmap , SizeOf( Test_Win30_Bitmap ));
  304.   {$I+}
  305.   The_IO_Result := IOResult;
  306.   If The_IO_Result <> 0 then
  307.   begin
  308.     Error_Status := -1;
  309.   end
  310.   else
  311.   begin
  312.     if Test_Win30_Bitmap = 40 then
  313.     begin
  314.       if Open_DIB then
  315.       begin
  316.         Load_Bitmap_File := true;
  317.       end;
  318.     end
  319.     else
  320.     begin
  321.       Error_Status := -2;
  322.     end;
  323.     CloseFile( The_File );
  324.   end;
  325. end;
  326.  
  327. { This does the actual loading of the bitmap's info }
  328. function File_BitMap.Open_DIB : Boolean;
  329. var
  330.   Bit_Count         : Word;
  331.   Size              : Word;
  332.   Long_Width        : Longint;
  333.   DC_Handle         : HDC;
  334.   Bits_Ptr          : Pointer;
  335.   Bitmap_Info       : PBitmapInfo;
  336.   New_Bitmap_Handle : THandle;
  337.   New_Pixel_Width,
  338.   New_Pixel_Height  : Word;
  339. begin
  340.   Open_DIB := true;
  341.   Seek( The_File , 28 );
  342.   BlockRead( The_File , Bit_Count , SizeOf( Bit_Count ));
  343.   if Bit_Count <= 8 then
  344.   begin
  345.     Size := SizeOf( TBitmapInfoHeader ) + (( 1 SHL Bit_Count )
  346.      * SizeOf( TRGBQuad ));
  347.     Bitmap_Info := MemAlloc( Size );
  348.     Seek( The_File , SizeOf( TBitmapFileHeader ));
  349.     BlockRead( The_File , Bitmap_Info^ , Size );
  350.     New_Pixel_Width := Bitmap_Info^.bmiHeader.biWidth;
  351.     New_Pixel_Height := Bitmap_Info^.bmiHeader.biHeight;
  352.     Long_Width := ((( New_Pixel_Width * Bit_Count ) + 31 ) div 32 ) * 4;
  353.     Bitmap_Info^.bmiHeader.biSizeImage := Long_Width * New_Pixel_Height;
  354.     {GlobalCompact( -1 );}
  355.     Bits_Handle := GlobalAlloc( gmem_Moveable or gmem_Zeroinit ,
  356.                                 Bitmap_Info^.bmiHeader.biSizeImage );
  357.     Bits_Byte_Size := Bitmap_Info^.bmiHeader.biSizeImage;
  358.     Get_Bitmap_Data;
  359.     DC_Handle := CreateDC( 'Display' , nil , nil , nil );
  360.     Bits_Ptr := GlobalLock( Bits_Handle );
  361.     New_Bitmap_Handle :=
  362.     CreateDIBitmap( DC_Handle , Bitmap_Info^.bmiHeader ,
  363.                     cbm_Init , Bits_Ptr , Bitmap_Info^ , 0 );
  364.     DeleteDC( DC_Handle );
  365.     GlobalUnlock( Bits_Handle );
  366.     GlobalFree( Bits_Handle );
  367.     FreeMem( Bitmap_Info , Size );
  368.     if New_Bitmap_Handle <> 0 then
  369.     begin
  370.       if Bitmap_Handle <> 0 then DeleteObject( Bitmap_Handle );
  371.       Bitmap_Handle := New_Bitmap_Handle;
  372.       Width := New_Pixel_Width;
  373.       Height := New_Pixel_Height;
  374.     end
  375.     else
  376.     begin
  377.       Open_DIB := false;
  378.       Error_Status := -4;
  379.     end;
  380.   end
  381.   else
  382.   begin
  383.     Open_DIB := false;
  384.     Error_Status := -3;
  385.   end;
  386. end;
  387.  
  388. { This is an OOP return of the error variable }
  389. function File_BitMap.Get_Error_Status : Integer;
  390. begin
  391.   Get_Error_Status := Error_Status;
  392. end;
  393.  
  394. { This is an OOP return of the dimensions of the DIB }
  395. procedure File_BitMap.Get_DIB_Dimensions( var The_Width  ,
  396.                                               The_Height   : Longint );
  397. begin
  398.   The_Width := Width;
  399.   The_Height := Height;
  400. end;
  401.  
  402. { Initialization method for FIP                                         }
  403. procedure TThumbNailFileIconPanel.Initialize( PanelX              ,
  404.                                      PanelY              ,
  405.                                      PanelWidth          ,
  406.                                      PanelHeight         ,
  407.                                      PanelBevelWidth     ,
  408.                                      LabelFontSize         : Integer;
  409.                                      PanelColor          ,
  410.                                      PanelHighlightColor ,
  411.                                      PanelShadowColor    ,
  412.                                      LabelTextColor        : TColor;
  413.                                      TheFilename         ,
  414.                                      LabelFontName         : String;
  415.                                      LabelFontStyle        : TFontStyles;
  416.                                      ExtraData             : Integer );
  417.  
  418. var TheLabelHeight ,             { Holder for label pixel height }
  419.     TheLabelWidth    : Integer;  { Holder for label pixel width  }
  420.     TheOtherPChar    : PChar;    { Windows ASCIIZ string         }
  421.     HolderBMP        : TBitmap;  { Holds working bitmap for tnail}
  422.     HoldName         : String;
  423.     TheBigBMP        : File_Bitmap;
  424. begin
  425.   { Set the basic properties based on imported parameters }
  426.   Left := PanelX;
  427.   Top := PanelY;
  428.   Width := PanelWidth;
  429.   Height := PanelHeight;
  430.   Color := PanelColor;
  431.   BevelWidth := PanelBevelWidth;
  432.   FHighlightColor := PanelHighlightColor;
  433.   FShadowColor := PanelShadowColor;
  434.   FTheName := TheFilename;
  435.   { If the ExtraData field is non-0 then a drive is being sent in }
  436.   if ExtraData <> 0 then
  437.   begin
  438.     GetIconForDrive( ExtraData , FTheIcon );
  439.     { The FileNme property is already set up for the caption; use directly }
  440.     FTheLabel.Caption := TheFilename;
  441.     { Set up the hint for later use (make sure to set ShowHint) }
  442.     Hint := 'Change to ' + TheFileName;
  443.     ShowHint := true;
  444.     { Set up all imported label properties and center it for drawing }
  445.     with FTheLabel do
  446.     begin
  447.       Font.Name := LabelFontName;
  448.       Font.Size := LabelFontSize;
  449.       Font.Style := LabelFontStyle;
  450.       Font.Color := LabelTextColor;
  451.       Canvas.Brush.Color := PanelColor;
  452.       Canvas.Font := Font;
  453.       TheLabelHeight := Canvas.Textheight( Caption ) + 4;
  454.       TheLabelWidth := Canvas.Textwidth( Caption ) + 4;
  455.       Left := (( Self.Width - TheLabelWidth ) div 2 ) + 1;
  456.       Top := ((( Round( Self.Height * 0.25 ) - 6 ) - TheLabelHeight) div 2) + 1;
  457.       Top := Top + Round( Self.Height * 0.75 );
  458.       Height := TheLabelHeight;
  459.       Width := TheLabelWidth;
  460.     end;
  461.   end
  462.   else
  463.   begin
  464.     GetIconForFile( FTheName , FTheIcon );
  465.     if FTheName = 'NO FILE' then
  466.     begin
  467.       FTheLabel.Caption := 'NO FILE';
  468.       Hint := 'Not Initialized';
  469.     end
  470.     else
  471.     begin
  472.       { A file or directory has been sent in; use GetIconForFile to obtain an }
  473.       { icon either from the file, its owner, or a RES file default.          }
  474.       GetIconForFile( FTheName , FTheIcon );
  475.       { Check for the Backup caption and set it specially }
  476.       if ExtractfileName( FThename ) = '..' then
  477.       begin
  478.         FTheLabel.Caption := '..';
  479.         Hint := 'Up One Level';
  480.       end
  481.       else
  482.       begin
  483.         if Uppercase( ExtractFileExt( FTheName )) = '.BMP' then
  484.         begin
  485.           TheBigBMP := File_Bitmap.Create;
  486.           TheBigBMP.Initialize( FTheName );
  487.           if TheBigBMP.Load_Bitmap_File then
  488.           begin
  489.             HolderBMP := TBitmap.Create;
  490.             HolderBMP.Handle := TheBigBMP.Get_Bitmap;
  491.             ThumbNailHeight := Round( Height * 0.5 );
  492.             ThumbNailWidth := Round( Width * 0.75 );
  493.             FTheBMP := CreateBitmapThumbNailFromBitmap( HolderBMP , ThumbNailWidth ,
  494.              ThumbNailHeight );
  495.             HolderBMP.Free;
  496.           end
  497.           else
  498.           begin
  499.             MessageDlg( 'Unable to Load ' + FTheName + ' Due to Code ' +
  500.              IntToStr( TheBigBMP.Get_Error_Status ),mtError,[mbok],0);
  501.             FTheBMP := Nil;
  502.           end;
  503.           TheBigBMP.Free;
  504.           FTheLabel.caption := ExtractFileName( UpperCase( FTheName ));
  505.           Hint := FTheName;
  506.         end
  507.         else
  508.         begin
  509.           { Otherwise just get the filename for the label caption }
  510.           { And the full path for the hint (used later.)          }
  511.           FTheLabel.caption := ExtractFileName( UpperCase( FTheName ));
  512.           Hint := FTheName;
  513.         end;
  514.       end;
  515.     end;
  516.     { Activate showhint so hints are seen }
  517.     ShowHint := true;
  518.     { Set label properties with imported values and center for display }
  519.     with FTheLabel do
  520.     begin
  521.       Font.Name := LabelFontName;
  522.       Font.Size := LabelFontSize;
  523.       Font.Style := LabelFontStyle;
  524.       Font.Color := LabelTextColor;
  525.       Canvas.Brush.Color := PanelColor;
  526.       Canvas.Font := Font;
  527.       TheLabelHeight := Canvas.Textheight( Caption ) + 4;
  528.       TheLabelWidth := Canvas.Textwidth( Caption ) + 4;
  529.       Left := (( Self.Width - TheLabelWidth ) div 2 ) + 1;
  530.       Top := ((( Round( Self.Height * 0.25 ) - 6 ) - TheLabelHeight) div 2) + 1;
  531.       Top := Top + Round( Self.Height * 0.75 );
  532.       Height := TheLabelHeight;
  533.       Width := TheLabelWidth;
  534.     end;
  535.   end;
  536. end;
  537.  
  538. { Paint method for FIP; overrides normal paint }
  539. procedure TThumbNailFileIconPanel.Paint;
  540. var
  541.   TheOtherRect   : TRect;   { Holds clientrect   }
  542.   TopColor     ,            { Holds bright color }
  543.   BottomColor    : TColor;  { Holds dark color   }
  544.  
  545. { These methods are from Borland Intl., copyright 1995 }
  546. procedure Frame3D(    Canvas       : TCanvas;
  547.                   var TheRect      : TRect;
  548.                       TopColor   ,
  549.                       BottomColor  : TColor;
  550.                       Width        : Integer );
  551.  
  552. procedure DoRect;
  553. var
  554.   TopRight, BottomLeft: TPoint;
  555. begin
  556.   with Canvas, TheRect do
  557.   begin
  558.     TopRight.X := Right;
  559.     TopRight.Y := Top;
  560.     BottomLeft.X := Left;
  561.     BottomLeft.Y := Bottom;
  562.     Pen.Color := TopColor;
  563.     PolyLine([BottomLeft, TopLeft, TopRight]);
  564.     Pen.Color := BottomColor;
  565.     Dec(BottomLeft.X);
  566.     PolyLine([TopRight, BottomRight, BottomLeft]);
  567.   end;
  568. end;
  569.  
  570. begin
  571.   Canvas.Pen.Width := 1;
  572.   Dec(TheRect.Bottom); Dec(TheRect.Right);
  573.   while Width > 0 do
  574.   begin
  575.     Dec(Width);
  576.     DoRect;
  577.     InflateRect(TheRect, -1, -1);
  578.   end;
  579.   Inc(TheRect.Bottom); Inc(TheRect.Right);
  580. end;
  581.  
  582. procedure AdjustColors(Bevel: TPanelBevel);
  583. begin
  584.   TopColor := FHighlightColor;
  585.   if Bevel = bvLowered then TopColor := FShadowColor;
  586.   BottomColor := FShadowColor;
  587.   if Bevel = bvLowered then BottomColor := FHighlightColor;
  588. end;
  589.  
  590. { Custom code begins here }
  591. begin
  592.   if OldName <> TheName then InitTheFIP;
  593.   if (( OldWidth <> Width ) or ( OldHeight <> Height )) then InitTheFIP;
  594.   { Get the rectangle of the control with API/method call }
  595.   TheOtherRect := GetClientRect;
  596.   { draw basic rectangle with basic color }
  597.   with Canvas do
  598.   begin
  599.     Brush.Color := Color;
  600.     FillRect(TheOtherRect);
  601.   end;
  602.   { Set up for top "icon" frame  and draw it with frame3d }
  603.   TheOtherRect.Right := Width;
  604.   TheOtherRect.Bottom := Round( Height * 0.75 ) - 6 ;
  605.   if BevelOuter <> bvNone then
  606.   begin
  607.     AdjustColors(BevelOuter);
  608.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  609.   end;
  610.   Frame3D(Canvas, TheOtherRect, Color, Color, BorderWidth);
  611.   if BevelInner <> bvNone then
  612.   begin
  613.     AdjustColors(BevelInner);
  614.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  615.   end;
  616.   { Do the same for the lower "label" frame }
  617.   TheOtherRect.Top := Round( Height * 0.75 ) - 5;
  618.   TheOtherRect.Left := 0;
  619.   TheOtherRect.Bottom := Height;
  620.   TheOtherRect.Right := Width;
  621.   if BevelOuter <> bvNone then
  622.   begin
  623.     AdjustColors(BevelOuter);
  624.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  625.   end;
  626.   Frame3D(Canvas, TheOtherRect, Color, Color, BorderWidth);
  627.   if BevelInner <> bvNone then
  628.   begin
  629.     AdjustColors(BevelInner);
  630.     Frame3D(Canvas, TheOtherRect, TopColor, BottomColor, BevelWidth);
  631.   end;
  632.   if Assigned( FTheBMP ) then
  633.   begin
  634.     {Canvas.BrushCopy( Rect( (( Width - ThumbNailWidth ) div 2 ) + 2 ,
  635.                             ( (( Round( Height * 0.75 ) - 6 ) - ThumbNailHeight ) div 2 ) + 1 ,
  636.                             ThumbNailWidth , ThumbNailHeight ) ,
  637.                       FTheBMP ,
  638.                       Rect( 0 , 0 , ThumbNailWidth , ThumbNailHeight ) , GlobalTransparentColor );}
  639.     Canvas.Draw( Round( Width * 0.125 ) + 1 ,
  640.                  Round( Height * 0.125 ) + 1, FTheBMP );
  641.   end
  642.   else
  643.   begin
  644.     { Then draw the icon using canvas draw method }
  645.     Canvas.Draw( (( Width - 32 ) div 2 ) + 1 ,
  646.     ((( Round( Height * 0.75 ) - 6 ) - 32 ) div 2 ) + 1 , FTheIcon );
  647.   end;
  648. end;
  649.  
  650. procedure Register;
  651. begin
  652.   RegisterComponents('Widgets', [TThumbNailFileIconPanel]);
  653. end;
  654.  
  655. end.
  656.